#include <all.H>
#include "adc.h"

// uint8_t out_flag = 0;
// uint8_t in_flag = 0;
// uint8_t ui_dat[3000];

uint8_t vol_cu_sence[2] = {0, 0};

extern int16_t vol_pwm_num;
// uint16_t ui_save_num = 0;

static code uint8_t pin_io[] = {33, 50, 35, 37, 71, 73, 42, 44, 21, 23, 25, 26, 74, 76, 45, 00};
static wire_handle_t iic;

void printf_16bit(uint16_t var)
{
    uint8_t i;
    for (i = 0; i < 16; i++)
    {
        if (var & 0x8000)
            myprintf("1");
        else
            myprintf("0");
        if (i == 3 || i == 7 || i == 11)
            myprintf(" ");
        var <<= 1;
    }
}

void set_pin_level(PIN pin, VOLTAGE_LEVEL level)
{
    gpio_write(pin_io[pin - 1], level);
}

VOLTAGE_LEVEL read_pin_level(PIN pin)
{
    return gpio_read(pin_io[pin - 1]);
}

void pmu_pin_set(uint8_t ch, uint8_t mode)
{
    switch (ch)
    {
    case 1:
        pin1_pmu = mode;
        break;
    case 2:
        pin2_pmu = mode;
        break;
    case 3:
        pin3_pmu = mode;
        break;
    case 4:
        pin4_pmu = mode;
        break;
    case 5:
        pin5_pmu = mode;
        break;
    case 6:
        pin6_pmu = mode;
        break;
    case 7:
        pin7_pmu = mode;
        break;
    case 8:
        pin8_pmu = mode;
        break;
    case 9:
        pin9_pmu = mode;
        break;
    case 10:
        pin10_pmu = mode;
        break;
    case 11:
        pin11_pmu = mode;
        break;
    case 12:
        pin12_pmu = mode;
        break;
    case 13:
        pin13_pmu = mode;
        break;
    case 14:
        pin14_pmu = mode;
        break;
    case 15:
        pin15_pmu = mode;
        break;
    case 16:
        pin16_pmu = mode;
        break;
    }
}
//	/*
// M1  M0
// 0   0 准双向
// 0   1 推挽
// 1   0 高阻
// 1   1 开漏
//*/
void comp_io_on(uint8_t ch)
{
    switch (ch)
    {
    case 1:
        P3M1 |= 0X08;
        P3M0 &= 0XF7;
        break; // P33
    case 2:
        P5M1 |= 0X01;
        P5M0 &= 0XFE;
        break; // P50
    case 3:
        P3M1 |= 0X20;
        P3M0 &= 0XDF;
        break; // P35
    case 4:
        P3M1 |= 0X80;
        P3M0 &= 0X7F;
        break; // P37
    case 5:
        P7M1 |= 0X02;
        P7M0 &= 0XFD;
        break; // P71
    case 6:
        P7M1 |= 0X08;
        P7M0 &= 0XF7;
        break; // P73
    case 7:
        P4M1 |= 0X04;
        P4M0 &= 0XFB;
        break; // 42
    case 8:
        P4M1 |= 0X10;
        P4M0 &= 0XEF;
        break; // 44
    case 9:
        P2M1 |= 0X02;
        P2M0 &= 0XFD;
        break; // 21
    case 10:
        P2M1 |= 0X08;
        P2M0 &= 0XF7;
        break; // 23
    case 11:
        P2M1 |= 0X20;
        P2M0 &= 0XDF;
        break; // 25
    case 12:
        P2M1 |= 0X40;
        P2M0 &= 0XBF;
        break; // 26
    case 13:
        P7M1 |= 0X10;
        P7M0 &= 0XEF;
        break; // 74
    case 14:
        P7M1 |= 0X40;
        P7M0 &= 0XBF;
        break; // 76
    case 15:
        P4M1 |= 0X20;
        P4M0 &= 0XDF;
        break; // 45
    case 16:
        P0M1 |= 0X01;
        P0M0 &= 0XFE;
        break; // 00
    default:
        break;
    }
}

void drv_io_on(uint8_t ch)
{
    switch (ch)
    {
    case 1:
        P3M0 |= 0X08;
        P3M1 &= 0XF7;
        break; // P33
    case 2:
        P5M0 |= 0X01;
        P5M1 &= 0XFE;
        break; // P50
    case 3:
        P3M0 |= 0X20;
        P3M1 &= 0XDF;
        break; // P35
    case 4:
        P3M0 |= 0X80;
        P3M1 &= 0X7F;
        break; // P37
    case 5:
        P7M0 |= 0X02;
        P7M1 &= 0XFD;
        break; // P71
    case 6:
        P7M0 |= 0X08;
        P7M1 &= 0XF7;
        break; // P73
    case 7:
        P4M0 |= 0X04;
        P4M1 &= 0XFB;
        break; // 42
    case 8:
        P4M0 |= 0X10;
        P4M1 &= 0XEF;
        break; // 44
    case 9:
        P2M0 |= 0X02;
        P2M1 &= 0XFD;
        break; // 21
    case 10:
        P2M0 |= 0X08;
        P2M1 &= 0XF7;
        break; // 23
    case 11:
        P2M0 |= 0X20;
        P2M1 &= 0XDF;
        break; // 25
    case 12:
        P2M0 |= 0X40;
        P2M1 &= 0XBF;
        break; // 26
    case 13:
        P7M0 |= 0X10;
        P7M1 &= 0XEF;
        break; // 74
    case 14:
        P7M0 |= 0X40;
        P7M1 &= 0XBF;
        break; // 76
    case 15:
        P4M0 |= 0X20;
        P4M1 &= 0XDF;
        break; // 45
    case 16:
        P0M0 |= 0X01;
        P0M1 &= 0XFE;
        break; // 00
    default:
        break;
    }
}

void sel_ic_out_pin(PIN pin, ...)
{
    uint8_t val = pin;
    va_list ap;
    va_start(ap, pin);
    while (val)
    {
        comp_io_on(val);
        val = va_arg(ap, uint8_t);
    }
    va_end(ap);
}

void sel_ic_in_pin(PIN pin, ...)
{
    uint8_t val = pin;
    va_list ap;
    va_start(ap, pin);
    while (val)
    {
        drv_io_on(val);
        val = va_arg(ap, uint8_t);
    }
    va_end(ap);
}

void set_ic_pin(VOLTAGE_LEVEL logic, PIN pin, ...)
{
    uint8_t val = pin;
    va_list ap;
    va_start(ap, pin);
    while (val)
    {
        set_pin_level(val, logic);
        val = va_arg(ap, uint8_t);
    }
    va_end(ap);
}

uint16_t comp_ic_pin(VOLTAGE_LEVEL logic, PIN pin, ...)
{
    uint8_t val = pin;
    uint16_t dat = 0;
    uint8_t i;
    va_list ap;

    if (logic > 1)
    {
        for (i = 16; i > 0; i--)
        {
            dat <<= 1;
            dat |= read_pin_level(i);
        }
        return dat;
    }

    va_start(ap, pin);

    while (val)
    {
        if (read_pin_level(val) != logic)
        {
            va_end(ap);
            return val;
        }
        val = va_arg(ap, uint8_t);
    }
    va_end(ap);
    return 0;
}

void relay_on(RELAY_CHANNEL num)
{
    switch (num)
    {
    case 1:
        relay_k1 = 1;
        break;
    case 2:
        relay_k2 = 1;
        break;
    case 3:
        relay_k3 = 1;
        break;
    case 4:
        relay_k4 = 1;
        break;
    default:
        break;
    }
}
void relay_off(RELAY_CHANNEL num)
{
    switch (num)
    {
    case 1:
        relay_k1 = 0;
        break;
    case 2:
        relay_k2 = 0;
        break;
    case 3:
        relay_k3 = 0;
        break;
    case 4:
        relay_k4 = 0;
        break;
    default:
        break;
    }
}

void power_on_v(CHANNEL ch, float v)
{

    if (ch == 1)
    {
        vol_cu_sence[0] = 1;
        set_vol(ch, v);
    }
    else if (ch == 2)
    {
        vol_cu_sence[1] = 1;
        set_vol(ch, v);
    }
}

void power_on_i(uint8_t ch, float i)
{
    ch = 0;
    i = 0;
    //  set_vol(ch,i);
    //	if(ch==1)
    //		vol_cu_sence[0]=1;
    //	else if(ch==2)
    //		vol_cu_sence[1]=1;
}

void power_off(CHANNEL ch)
{
    set_vol(ch, 0);
    if (ch == 1)
    {
        f1_up = 0;
        f1_down = 0;
    }
    if (ch == 2)
    {
        f2_up = 0;
        f2_down = 0;
    }
    if (ch == 1)
        vol_cu_sence[0] = 0;
    else if (ch == 2)
        vol_cu_sence[1] = 0;
}
// void ui_clean()
// {
//     uint16_t i;
//     // ui_save_num = 0;
//     //memset(ui_dat, 0, sizeof(ui_dat));
// }

float get_pin_voltage(PIN pin)
{
    float x;
    pmu_pin_set(pin, 1);
    vol_io = 1;
    delay(5);
    x = get_vol();
    pmu_pin_set(pin, 0);
    vol_io = 0;
    delay(2);
    return x;
}

float get_force_pmu(CHANNEL ch, VOL_CU_CH v_i)
{
    float x = 0;

    if (ch == 1)
    {
        if (v_i == 1)
        {
            f1_io = 1;
            vol_io = 1;
            delay(5);
            x = get_vol();
            f1_io = 0;
            vol_io = 0;
            delay(2);
        }
        else if (v_i == 2)
        {
            x = get_cu(1);
        }
    }
    else if (ch == 2)
    {
        if (v_i == 1)
        {
            f2_io = 1;
            vol_io = 1;
            delay(5);
            x = get_vol();
            f2_io = 0;
            vol_io = 0;
            delay(2);
        }
        else if (v_i == 2)
        {
            x = get_cu(2);
        }
    }
    return x;
}

void sys_reset()
{
    uint8_t x;
    test_error_led = 0;
    test_pass_led = 0;
    power_off(1);
    power_off(2);
    sel_ic_out_pin(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0);
    relay_off(1);
    relay_off(2);
    relay_off(3);
    relay_off(4);

    delay(2);
}

void power_off_all()
{

    power_off(1);
    power_off(2);
    f1_up = 0;
    f1_down = 0;
    f2_up = 0;
    f2_down = 0;
    relay_off(1);
    relay_off(2);
    relay_off(3);
    relay_off(4);
}

float pin_vi_test(PIN pin, CHANNEL ch, float voltage)
{
    float x = 0;
    if (pin && !vol_cu_sence[(ch - 1)])
    {
        power_on_v(ch, voltage);
        if (ch == 1)
        {
            f1_io = 1;
        }
        if (ch == 2)
            f2_io = 1;
        pmu_pin_set(pin, 1);
        delay(3);
        x = get_cu(ch);
        pmu_pin_set(pin, 0);
        power_on_v(ch, 0);
        vol_cu_sence[(ch - 1)] = 0;
    }
    return x;
}

float pin_iv_test(PIN pin, CHANNEL ch, float current)
{
    idata float x = 0;
    idata uint8_t flag = 0; // 0正常  1小于0
    idata uint8_t vol_flag = 0;
    idata uint8_t vol_flag_1 = 0;
    bit os_test_flg = 0;

    if (current < 0)
        flag = 1;
    if (current == -100)
    {
        current = -500;
        os_test_flg = 1;
    }

    //////////////////////////
    /*
    同步电压
    */
    if (pin && !vol_cu_sence[(ch - 1)])
    {
        pmu_pin_set(pin, 1);
        vol_io = 1;
        delay(3);
        x = get_vol();
        if (x < 0)
        {
            vol_flag = 1;
            vol_flag_1 = 1;
        }
        pmu_pin_set(pin, 0);
        if (os_test_flg)
            power_on_v(ch, -0.25);
        else
            power_on_v(ch, x);
        if (ch == 1)
            f1_io = 1;
        if (ch == 2)
            f2_io = 1;
        pmu_pin_set(pin, 1);
        delay(3);
        ///////////////////////
        while (1)
        {
            x = get_cu(ch);
            if (flag)
            {
                if (x <= current)
                    break;
                if (vol_flag_1)
                    vol_pwm_num += 50;
                else
                    vol_pwm_num -= 50;
            }
            else
            {
                if (x >= current)
                    break;
                if (vol_flag_1)
                    vol_pwm_num -= 50;
                else
                    vol_pwm_num += 50;
            }

            if (vol_pwm_num >= 32567)
            {
                break;
            }
            if (vol_pwm_num < 0)
            {
                if (!vol_flag)
                {
                    if (ch == 1)
                    {
                        f1_up = 0;
                        f1_down = 1;
                    }
                    if (ch == 2)
                    {
                        f2_up = 0;
                        f2_down = 1;
                    }
                    vol_flag_1 = !vol_flag_1;
                    vol_pwm_num = 0;
                    delay(2);
                }
                else
                {
                    if (ch == 1)
                    {
                        f1_up = 1;
                        f1_down = 0;
                    }
                    if (ch == 2)
                    {
                        f2_up = 1;
                        f2_down = 0;
                    }
                    vol_flag_1 = !vol_flag_1;
                    vol_pwm_num = 0;
                    delay(2);
                }
            }
            set_pwm_num(ch, vol_pwm_num);
            delay(3);
        }
        vol_io = 1;
        delay(3);
        x = get_vol();

        pmu_pin_set(pin, 0);
        power_on_v(ch, 0);

        delay(1);
        vol_cu_sence[(ch - 1)] = 0;
    }
    return x;
}

uint16_t get_pin_data()
{
    uint16_t x;
    uint8_t i;
    for (i = 16; i > 0; i--)
    {
        x |= read_pin_level(i) << (i - 1);
    }
    return x;
}

void test_pass()
{
    test_pass_led = 1;
    test_error_led = 0;
}

void test_fail()
{
    test_pass_led = 0;
    test_error_led = 1;
}

static void create_iic(uint8_t sda, uint8_t scl)
{
    wire_config_t cfg;
    cfg.gpio_get_level = gpio_read;
    cfg.gpio_set_level = gpio_write;
    cfg.scl = scl;
    cfg.sda = sda;
    iic = wire_creat(&cfg);

    gpio_mode(sda, OUTPUT_PULLUP);
    gpio_mode(scl, OUTPUT_PULLUP);
}

test_ret_t test_iic_write(PIN SDA_PIN, PIN SCL_PIN, uint8_t dev_addr, uint8_t reg_addr, uint8_t *write_buffer, size_t lenth)
{
    test_ret_t ret = TEST_IIC_PASS;
    if (dev_addr < 2)
        return TEST_IIC_ADDRESS_ERR;
    if (SDA_PIN < 1 || SCL_PIN < 1 || SDA_PIN > 16 || SCL_PIN > 16)
        return TEST_IIC_PIN_ERR;

    SDA_PIN -= 1;
    SCL_PIN -= 1;

    create_iic(pin_io[SDA_PIN], pin_io[SCL_PIN]);

    if (wire_write_bytes(iic, dev_addr, reg_addr, write_buffer, lenth) == 0)
        ret = TEST_IIC_NO_DEVICE;

    wire_delete(iic);
    gpio_mode(pin_io[SDA_PIN], INPUT);
    gpio_mode(pin_io[SCL_PIN], INPUT);

    return ret;
}

test_ret_t test_iic_read(PIN SDA_PIN, PIN SCL_PIN, uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_buffer, size_t lenth)
{
    test_ret_t ret = TEST_IIC_PASS;
    if (dev_addr < 2)
        return TEST_IIC_ADDRESS_ERR;
    if (SDA_PIN < 1 || SCL_PIN < 1 || SDA_PIN > 16 || SCL_PIN > 16)
        return TEST_IIC_PIN_ERR;

    SDA_PIN -= 1;
    SCL_PIN -= 1;

    create_iic(pin_io[SDA_PIN], pin_io[SCL_PIN]);

    if (wire_read_bytes(iic, dev_addr, reg_addr, read_buffer, lenth) == 0)
        ret = TEST_IIC_NO_DEVICE;

    wire_delete(iic);
    gpio_mode(pin_io[SDA_PIN], INPUT);
    gpio_mode(pin_io[SCL_PIN], INPUT);

    return ret;
}

test_ret_t test_iic_scan_devices(PIN SDA_PIN, PIN SCL_PIN)
{
    test_ret_t ret = TEST_IIC_PASS;
    uint8_t add_buffer[130];

    if (SDA_PIN < 1 || SCL_PIN < 1 || SDA_PIN > 16 || SCL_PIN > 16)
        return TEST_IIC_PIN_ERR;

    SDA_PIN -= 1;
    SCL_PIN -= 1;

    create_iic(pin_io[SDA_PIN], pin_io[SCL_PIN]);

    wire_scan_device(iic, add_buffer);
    myprintf("iic devices num is %bu\n", add_buffer[0]);
    if (add_buffer[0] == 0)
        ret = TEST_IIC_NO_DEVICE;
    else
    {
        for (add_buffer[129] = 0; add_buffer[129] < add_buffer[0]; add_buffer[129]++)
        {
            myprintf("iic device %bu address is %bu\n", add_buffer[129] + 1, add_buffer[add_buffer[129] + 1]);
        }
    }
    wire_delete(iic);
    gpio_mode(pin_io[SDA_PIN], INPUT);
    gpio_mode(pin_io[SCL_PIN], INPUT);
    return ret;
}
